package org.reborn.engine.model.mesh

import org.reborn.math._

import org.reborn.engine.enums.ArrayType
import org.reborn.engine.enums.FaceMode._

import java.nio.FloatBuffer
import java.nio.IntBuffer
 

class ImmutableVertexData(private val arrayType:ArrayType.ArrayType,private val pPVertex:Int,data:Array[Float]) extends VertexData{
  require(data.length % partsPerVertex == 0)
  
  private val vertData = java.util.Arrays.copyOf(data,data.length)
  
  def aType():ArrayType.ArrayType = arrayType
  def partsPerVertex():Int = pPVertex
  def verts():Int = data.length /pPVertex
  def arraySize():Int = data.length
  
  def getDataArray() = java.util.Arrays.copyOf(vertData,vertData.length)
  
  def getDataBuffer() = FloatBuffer.wrap(getDataArray)
  
  def apply(position:Int):Float = vertData(position);
  
  def getVertexAt(vertIndex:Int):VectorF = {
    val startInd = vertIndex * pPVertex
    var partList:List[Float] = Nil
    for(i <- startInd until (startInd + pPVertex) ){ partList = vertData(i) :: partList }
    
    VectorF(partList.reverse)
  }
}

class ImmutableMesh(vertDataArrays:List[ImmutableVertexData],faceDataArray:Array[Int],private val fMode:FaceMode) extends Mesh{
  //Create a map from the list of VertexData objects
  //using aType as the key, and the VertexData object as the value
  private val arrayTypeMap:Map[ArrayType.ArrayType,VertexData] = {
    Map() ++( vertDataArrays.map((data)=>{ (data.aType,data) }))
  }
  
  private val faceData = java.util.Arrays.copyOf(faceDataArray,faceDataArray.length)
  private val faceDataCount = faceData.length
  
  private var faceBuffer:IntBuffer = null;
  
  fMode match{
    case Line => require(faceDataCount % 2 == 0)
    case Triangle => require(faceDataCount %3 == 0)
    case Quad => require(faceDataCount %4 == 0)
    case _ =>
  }
  require(this hasType ArrayType.Vertex)
  
  def verticesPerFace:Int = fMode.id + 1
  
  def getAvailableArrayTypes():Iterable[ArrayType.ArrayType] = arrayTypeMap.keySet
  def hasType(arrayType:ArrayType.ArrayType):Boolean = arrayTypeMap.contains(arrayType)
  def apply(arrayType:ArrayType.ArrayType):VertexData = arrayTypeMap(arrayType);
  
  def getFacesArray():Array[Int] = java.util.Arrays.copyOf(faceData,faceData.length)
  def getFacesBuffer():IntBuffer = IntBuffer.wrap(getFacesArray)
  
  def getFaceMode():FaceMode = fMode
  
  def verts():Int = arrayTypeMap(ArrayType.Vertex).verts
  def faces():Int = faceDataCount / verticesPerFace

  protected def getTranslatedVertexIndex(faceIndex:Int):Int = faceData(faceIndex);
  
}